import sys, os, shutil, time, stat
import hashlib

class FileHash(object):
    def __hash_file(self, filepath):
        if os.path.exists(filepath):
            with open(filepath, 'rb') as fin:
                hash= hashlib.md5()
                while True:
                    data= fin.read(8096)
                    if not data:
                        break
                    hash.update(data)
                return hash.hexdigest()
    
    def compare_file(self, srcfile, destfile):
        src_md5= self.__hash_file(srcfile)
        dest_md5= self.__hash_file(destfile)
        isOk= (src_md5==dest_md5)
        return isOk

def print_log(msg, fout):
    print(msg, file= fout)
    if fout!= sys.stdout:
        print(msg)

def update_file(srcfile, destfile, fout= sys.stdout):
    '''检查是否需要更新文件'''
    if not os.path.exists(destfile):
        # 目标文件不存在
        shutil.copy2(srcfile, destfile)
        print_log('Copied file:      %s'%destfile, fout)
    elif os.stat(srcfile)[stat.ST_MTIME] > os.stat(destfile)[stat.ST_MTIME] and not file_hash.compare_file(srcfile, destfile):
        # 目标文件存在，但md5值不同
        os.chmod(destfile, stat.S_IWRITE)
        shutil.copy2(srcfile, destfile)
        print_log('overwrite file:    %s'%destfile, fout)    

def update_dir(srcdir, destdir, fout= sys.stdout):
    '''更新目录文件'''
#    # 目录被修改过
#    if os.stat(srcdir)[stat.ST_MTIME] > os.stat(destdir)[stat.ST_MTIME]:        
    for root, dirs, files in os.walk(srcdir):
        # 目录遍历
        for dirname in dirs:
            src_dir_path    = os.path.join(root, dirname)
            dest_dir_path   = os.path.join(destdir, src_dir_path[len(srcdir)+1:])

            if not os.path.exists(dest_dir_path):
                # 目标目录不存在
                prompt= input('Will create dir: %s, Y/N ? Enter for Not\n >>> '%(dest_dir_path))
                if prompt in ('y', 'yes', 'Y', 'YES'):
                    shutil.copytree(src_dir_path, dest_dir_path)
                    print_log('Copied dir:       %s'%dest_dir_path, fout)
                else:
                    print_log('Skipped dir:       %s'%dest_dir_path, fout)
                # 文件遍历过程中不需要再访问此目录
                dirs.remove(dirname)
        # 文件遍历
        for filename in files:
            # 不更新mpx文件
            if not filename.endswith('.mpx'):
                src_file_path   = os.path.join(root, filename)
                dest_file_path  = os.path.join(destdir, src_file_path[len(srcdir)+1:])
                # 更新目标文件
                update_file(src_file_path, dest_file_path, fout)
            
                
if __name__ == '__main__':
    start_time= time.time()
    file_hash= FileHash()
    srcroot  =r'\\jiangdalong\bin'
    destroot =r'D:\me\document\VC6\DanceWorld\bin'
    excluded_names= set(('bbsfiles', 'BBSPages', 'Configs', 'cache', 'logs','MyMovies', 'MyMusics', 'Res', 'screenshots', 'script', 'Shaders', 'surfaces', 'Temp', 'userdata', 
                 'DanceClient.exe', 'DanceClient_d.exe', 'DWFileConverter.py', 'log.txt'))
    
    logpath= os.path.basename(__file__)+'.log'
    with open(logpath, 'w') as fout:
        candidate_names= os.listdir(srcroot)
        
        for candidate_name in candidate_names:
            if candidate_name not in excluded_names \
                and not candidate_name.endswith('.ilk') \
                and not candidate_name.endswith('.lnk') \
                and not candidate_name.startswith('RWItemSee'):
                
                srcpath= os.path.join(srcroot, candidate_name)
                destpath= os.path.join(destroot, candidate_name)
                if os.path.isdir(srcpath):
                    update_dir(srcpath, destpath, fout)
                else:
                    update_file(srcpath, destpath, fout)
        end_time= time.time()
        print_log('\nTotal spend time: %f seconds'% (end_time- start_time), fout)
        
    os.startfile(logpath)


